#include "sd_card.h"
#include "sd_protocol_defs.h"

static const char *TAG = "sd_card";

/**
 * @brief 获取SD卡详细信息
 */
esp_err_t sd_card_get_info(sdmmc_card_t *card, sd_card_info_t *info)
{
    if (card == NULL || info == NULL) {
        return ESP_ERR_INVALID_ARG;
    }

    // 设置卡名称
    strlcpy(info->name, (char*)card->cid.name, sizeof(info->name));

    // 设置卡类型
    if (card->is_sdio) {
        strlcpy(info->type, "SDIO", sizeof(info->type));
    } else if (card->is_mmc) {
        strlcpy(info->type, "MMC", sizeof(info->type));
    } else {
        if ((card->ocr & SD_OCR_SDHC_CAP) == 0) {
            strlcpy(info->type, "SDSC", sizeof(info->type));
        } else {
            if (card->ocr & SD_OCR_S18_RA) {
                strlcpy(info->type, "SDHC/SDXC (UHS-I)", sizeof(info->type));
            } else {
                strlcpy(info->type, "SDHC", sizeof(info->type));
            }
        }
    }

    // 设置速度信息
    if (card->real_freq_khz == 0) {
        strlcpy(info->speed, "N/A", sizeof(info->speed));
    } else {
        const char *freq_unit = card->real_freq_khz < 1000 ? "kHz" : "MHz";
        const float freq = card->real_freq_khz < 1000 ? card->real_freq_khz : card->real_freq_khz / 1000.0;
        const char *max_freq_unit = card->max_freq_khz < 1000 ? "kHz" : "MHz";
        const float max_freq = card->max_freq_khz < 1000 ? card->max_freq_khz : card->max_freq_khz / 1000.0;
        
        snprintf(info->speed, sizeof(info->speed), "%.2f %s (limit: %.2f %s)%s", 
                 freq, freq_unit, max_freq, max_freq_unit, 
                 card->is_ddr ? ", DDR" : "");
    }

    // 设置容量（MB）
    info->size_mb = ((uint64_t) card->csd.capacity) * card->csd.sector_size / (1024 * 1024);

    // 设置CSD信息
    info->csd.ver = card->is_mmc ? card->csd.csd_ver : card->csd.csd_ver + 1;
    info->csd.sector_size = card->csd.sector_size;
    info->csd.capacity = card->csd.capacity;
    info->csd.read_bl_len = card->csd.read_block_len;

    // 设置SSR信息（对于SD卡）或EXT CSD信息（对于MMC卡）
    if (card->is_mmc) {
        info->ssr.bus_width = (uint32_t)(1 << card->log_bus_width);
    } else if (!card->is_sdio) { // 确保是SD卡
        info->ssr.bus_width = (uint32_t)(card->ssr.cur_bus_width ? 4 : 1);
    } else {
        info->ssr.bus_width = 0; // 对于SDIO卡，设置为0
    }

    return ESP_OK;
}

esp_err_t sd_card_init_and_mount(const char *mount_point, sdmmc_card_t **card)
{
    esp_err_t ret;

    esp_vfs_fat_sdmmc_mount_config_t mount_config = {
        .format_if_mount_failed = true,   // 如果挂载不成功是否需要格式化SD卡
        .max_files = 5, // 允许打开的最大文件数
        .allocation_unit_size = 16 * 1024  // 分配单元大小
    };

    ESP_LOGI(TAG, "Initializing SD card");
    ESP_LOGI(TAG, "Using SDMMC peripheral");

    sdmmc_host_t host = SDMMC_HOST_DEFAULT(); // SDMMC主机接口配置
    sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); // SDMMC插槽配置
    slot_config.width = 1;  // 设置为1线SD模式
    slot_config.clk = BSP_SD_CLK;
    slot_config.cmd = BSP_SD_CMD;
    slot_config.d0 = BSP_SD_D0;
    slot_config.flags |= SDMMC_SLOT_FLAG_INTERNAL_PULLUP; // 打开内部上拉电阻

    ESP_LOGI(TAG, "Mounting filesystem");
    ret = esp_vfs_fat_sdmmc_mount(mount_point, &host, &slot_config, &mount_config, card); // 挂载SD卡

    if (ret != ESP_OK) {  // 如果没有挂载成功
        if (ret == ESP_FAIL) { // 如果挂载失败
            ESP_LOGE(TAG, "Failed to mount filesystem. ");
        } else { // 如果是其它错误 打印错误名称
            ESP_LOGE(TAG, "Failed to initialize the card (%s). ", esp_err_to_name(ret));
        }
        return ret;
    }
    ESP_LOGI(TAG, "Filesystem mounted"); // 提示挂载成功
    sdmmc_card_print_info(stdout, *card); // 终端打印SD卡的一些信息

    return ESP_OK;
}

void sd_card_unmount(const char *mount_point, sdmmc_card_t *card)
{
    esp_vfs_fat_sdcard_unmount(mount_point, card);
    ESP_LOGI(TAG, "Card unmounted");
}